//
// DepTreePrinter
//
// Copyright (C) jextra.net.
//
//  This file is part of the net.jextra.dep Library.
//
//  The net.jextra.dep Library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  The net.jextra.dep Library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with the net.jextra.dep Library; if not, write to the Free
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
//  02111-1307 USA.
//

package net.jextra.dep;

import java.io.*;

/**
 * <p>
 * Output dependency model in a pretty format.
 * </p>
 */
public class DepTreePrinter
{
    // ============================================================
    // Fields
    // ============================================================

    public static final int INDENT_SIZE = 4;

    private boolean showMissingComponents;

    private PrintStream out;

    // ============================================================
    // Constructors
    // ============================================================

    public DepTreePrinter()
    {
        showMissingComponents = false;
    }

    // ============================================================
    // Methods
    // ============================================================

    // ----------
    // public
    // ----------

    public void print( DepTree model, PrintStream out )
        throws Exception
    {
        this.out = out;

        out.println();
        for ( DepComponent component : model.getRootComponents() )
        {
            out.printf( "%s\n", getComponentText( component ) );

            printChildren( component, "", 1 );
        }
        out.println();
    }

    public void setShowMissingComponents( boolean showMissingComponents )
    {
        this.showMissingComponents = showMissingComponents;
    }

    // ----------
    // private
    // ----------

    private void printChildren( DepComponent component, String prefix, int indent )
        throws Exception
    {
        //
        // Find last component.
        //
        DepComponent lastComponent = null;
        DepDependency lastDep = null;
        for ( DepComponent child : component.getChildren() )
        {
            lastComponent = child;
        }

        if ( showMissingComponents )
        {
            for ( DepDependency dep : component.getMissingDependencies() )
            {
                lastComponent = null;
                lastDep = dep;
            }
        }

        //
        // Print.
        //
        for ( DepComponent child : component.getChildren() )
        {
            String stub = "+-";
            String nextStub = "|  ";
            if ( lastComponent == child )
            {
                stub = "\\-";
                nextStub = "   ";
            }
            out.printf( "%s%s %s\n", prefix, stub, getComponentText( child ) );

            printChildren( child, prefix + nextStub, indent + 1 );
        }

        if ( showMissingComponents )
        {
            for ( DepDependency dep : component.getMissingDependencies() )
            {
                out.printf( "%s%s %s  %s <<MISSING>>\n", prefix, lastDep == dep ? "\\-" : "+-", dep.getName(), dep.getVersionPattern() );
            }
        }
    }

    private String getComponentText( DepComponent component )
    {
        //        String string = component.getName().replace( '/', '.' );
        //        int period = string.lastIndexOf( '.' );
        //        string = string.substring( 0, period ) + ":" + string.substring( period + 1 );

        DepDependency dep = component.getSeedDependency();
        String scope = "compile";
        if ( dep != null && dep.getScope() != null )
        {
            scope = dep.getScope();
        }

        if ( "compile".equalsIgnoreCase( scope ) )
        {
            return String.format( "%s  %s", component.getName(), component.getVersionNumber() );
        }
        else
        {
            return String.format( "%s  %s (%s)", component.getName(), component.getVersionNumber(), scope );
        }
    }
}
